﻿namespace SharpF2.Services
{
	using System;
	using System.Collections.Generic;
	using System.Collections.ObjectModel;
	using System.Globalization;
	using System.IO;
	using System.Linq;
	using System.Reflection;
	using System.Resources;
	using System.Threading;
	using System.Windows;
	using Properties;

	public class LanguageService
	{
		#region Events

		public static event EventHandler UICultureChanged
		{
			add { uiCultureChangedHandlers.Add(value); }
			remove { uiCultureChangedHandlers.Remove(value); }
		}

		#endregion

		#region Constructors

		static LanguageService()
		{
			// Load user language
			var cultures = GetAvailableCultures();
			var userCulture = Settings.Default.LanguageLCID;
			var culture = cultures.First(c => userCulture.Equals(c.LCID));
			if (null != culture)
				UICulture = culture;
		}

		#endregion

		#region Private Attributes

		private static readonly HashSet<EventHandler> uiCultureChangedHandlers = new HashSet<EventHandler>();


		// Available cultures
		private static ReadOnlyCollection<CultureInfo> _availableCultures;

		private static ResourceManager _resourceManager;

		#endregion

		#region Public Properties

		public static ReadOnlyCollection<CultureInfo> AvailableCultures
		{
			get
			{
				if (_availableCultures == null)
				{
					_availableCultures = GetAvailableCultures();
				}
				return _availableCultures;
			}
		}

		public static ResourceManager ResourceManager
		{
			get
			{
				if (_resourceManager == null)
				{
					_resourceManager = GetResourceManager();
				}
				return _resourceManager;
			}
			set { _resourceManager = value; }
		}

		public static CultureInfo UICulture
		{
			get { return Thread.CurrentThread.CurrentUICulture; }
			set
			{
				Thread.CurrentThread.CurrentUICulture = value;
				Settings.Default.LanguageLCID = value.LCID;
				Settings.Default.Save();
				OnUICultureChanged();
			}
		}

		#endregion

		#region Private Members

		private static Assembly GetAssembly()
		{
			var asm = Assembly.GetEntryAssembly() ?? (
			                                         	from a in AppDomain.CurrentDomain.GetAssemblies()
			                                         	where a.EntryPoint != null
			                                         	      && a.GetTypes().Any(t => t.IsSubclassOf(typeof (Application)))
			                                         	select a
			                                         ).FirstOrDefault();
			return asm;
		}

		private static ReadOnlyCollection<CultureInfo> GetAvailableCultures()
		{
			var list = new List<CultureInfo>();

			var startupDir = Environment.CurrentDirectory;
			var asm = GetAssembly();

			var neutralCulture = CultureInfo.InvariantCulture;
			if (asm != null)
			{
				var attr =
					Attribute.GetCustomAttribute(asm, typeof (NeutralResourcesLanguageAttribute)) as NeutralResourcesLanguageAttribute;
				if (attr != null)
					neutralCulture = CultureInfo.GetCultureInfo(attr.CultureName);
			}
			list.Add(neutralCulture);

			if (asm != null)
			{
				var baseName = asm.GetName().Name;
				foreach (var dir in Directory.GetDirectories(startupDir))
				{
					// Check if the name folder represent a valid culture
					var dirinfo = new DirectoryInfo(dir);
					CultureInfo tCulture;
					try
					{
						tCulture = CultureInfo.GetCultureInfo(dirinfo.Name);
					}
					catch (ArgumentException)
					{
						continue;
					}

					if (dirinfo.GetFiles(baseName + ".resources.dll").Length > 0)
					{
						list.Add(tCulture);
					}
				}
			}
			return list.AsReadOnly();
		}

		private static ResourceManager GetResourceManager()
		{
			var asm = GetAssembly();

			if (asm != null)
			{
				var baseName = asm.GetName().Name + ".Properties.Resources";
				var rm = new ResourceManager(baseName, asm);
				return rm;
			}
			return null;
		}


		private static void OnUICultureChanged()
		{
			var copy = new HashSet<EventHandler>(uiCultureChangedHandlers);
			foreach (var handler in copy)
				handler(typeof (LanguageService), EventArgs.Empty);
		}

		#endregion
	}
}